home *** CD-ROM | disk | FTP | other *** search
- /* x11_windows.c -- Window handling for X11
- Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
-
- This file is part of Jade.
-
- Jade is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- Jade is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Jade; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "jade.h"
- #include "jade_protos.h"
- #include "revision.h"
-
- #include <string.h>
- #include <X11/Xutil.h>
-
- _PR int sys_sleep_vw(VW *);
- _PR int sys_unsleep_vw(VW *);
- _PR void sys_new_vw(VW *);
- _PR void sys_kill_vw(VW *);
- _PR void sys_update_dimensions(VW *);
- _PR void x11_update_dimensions(VW *, int, int);
- _PR Window sys_new_window(VW *, VW *, bool);
- _PR void sys_kill_window(VW *);
- _PR void sys_activate_win(VW *);
- _PR void sys_set_vw_pos(VW *, long, long, long, long);
- _PR VW *x11_find_window_view(Window);
- _PR int sys_set_font(VW *);
- _PR void sys_unset_font(VW *);
- _PR void sys_reset_sleep_titles(TX *);
- _PR bool sys_get_mouse_pos(POS *, VW *);
- _PR void sys_windows_init(void);
-
- #define INPUT_EVENTS ButtonPressMask | ButtonReleaseMask | KeyPressMask \
- | ExposureMask | StructureNotifyMask | FocusChangeMask
-
- static XSizeHints size_hints;
- static XClassHint class_hints = { "jade", "Editor" };
- static XWMHints wm_hints;
-
- /* Let the window-manager handle all iconifying... */
- int
- sys_sleep_vw(VW *vw)
- {
- if((vw->vw_Flags & VWFF_SLEEPING) == 0)
- {
- XIconifyWindow(x11_display, vw->vw_Window, x11_screen);
- vw->vw_Flags |= VWFF_SLEEPING;
- }
- return(TRUE);
- }
-
- int
- sys_unsleep_vw(VW *vw)
- {
- if(vw->vw_Flags & VWFF_SLEEPING)
- {
- /* Does this work?? */
- wm_hints.flags |= StateHint;
- wm_hints.initial_state = IconicState;
- XSetWMHints(x11_display, vw->vw_Window, &wm_hints);
- XMapWindow(x11_display, vw->vw_Window);
- vw->vw_Flags &= ~VWFF_SLEEPING;
- }
- return(TRUE);
- }
-
- void
- sys_new_vw(VW *vw)
- {
- }
-
- void
- sys_kill_vw(VW *vw)
- {
- }
-
- void
- sys_update_dimensions(VW *vw)
- {
- XWindowAttributes xwa;
- XGetWindowAttributes(x11_display, vw->vw_Window, &xwa);
- x11_update_dimensions(vw, xwa.width, xwa.height);
- }
-
- void
- x11_update_dimensions(VW *vw, int width, int height)
- {
- if(vw->vw_Window && ((vw->vw_Flags & VWFF_SLEEPING) == 0))
- {
- vw->vw_MessageLineY = height - vw->vw_FontY - 2;
- vw->vw_MessageFontY = vw->vw_MessageLineY + 2 + FONT_ASCENT(vw);
-
- vw->vw_XStartPix = 0;
- vw->vw_YStartPix = 0;
- /*
- * only measure *text* area, not where messages go
- */
- vw->vw_XEndPix = width;
- vw->vw_YEndPix = (vw->vw_MessageLineY - 1);
- vw->vw_XWidthPix = vw->vw_XEndPix - vw->vw_XStartPix;
- vw->vw_YHeightPix = vw->vw_YEndPix - vw->vw_YStartPix;
-
- vw->vw_FontStart = vw->vw_YStartPix + vw->vw_Font->ascent;
-
- vw->vw_MaxX = (vw->vw_XWidthPix / vw->vw_FontX);
- vw->vw_MaxY = (vw->vw_YHeightPix / vw->vw_FontY);
- if((vw->vw_XStepRatio <= 0)
- || ((vw->vw_XStep = vw->vw_MaxX / vw->vw_XStepRatio) <= 0))
- vw->vw_XStep = 1;
- if((vw->vw_YStepRatio <= 0)
- || ((vw->vw_YStep = vw->vw_MaxY / vw->vw_YStepRatio) <= 0))
- vw->vw_YStep = 1;
- }
- }
-
- /*
- * The only thing necessary in `vw' is the font stuff (I think)
- */
- Window
- sys_new_window(VW *oldVW, VW *vw, bool useDefDims)
- {
- unsigned int x, y, width, height;
- Window win;
- size_hints.flags = 0;
- if(!useDefDims && oldVW)
- {
- x = y = 0;
- width = vw->vw_FontX * oldVW->vw_MaxX;
- height = (vw->vw_FontY * (oldVW->vw_MaxY + 1)) + 3;
- size_hints.flags |= PPosition | PSize;
- }
- else
- {
- if(def_dims[0] != -1)
- {
- x = def_dims[0];
- size_hints.flags |= USPosition;
- }
- else
- x = 0;
- if(def_dims[1] != -1)
- {
- y = def_dims[1];
- size_hints.flags |= USPosition;
- }
- else
- y = 0;
- if(def_dims[2] != -1)
- {
- width = def_dims[2];
- size_hints.flags |= USSize;
- }
- else
- width = 80;
- if(def_dims[3] != -1)
- {
- height = def_dims[3];
- size_hints.flags |= USSize;
- }
- else
- height = 24;
- width = vw->vw_FontX * width;
- height = (vw->vw_FontY * (height + 1)) + 3;
- }
- win = XCreateSimpleWindow(x11_display, DefaultRootWindow(x11_display),
- x, y, width, height,
- 1, x11_fore_pixel, x11_back_pixel);
- if(win)
- {
- XGCValues xgcv;
- vw->vw_Window = win;
- /*
- * xgcv.plane_mask = x11_fore_pixel | x11_back_pixel;
- */
- xgcv.foreground = x11_fore_pixel;
- xgcv.background = x11_back_pixel;
- xgcv.line_width = 1;
- xgcv.font = vw->vw_Font->fid;
- vw->vw_WindowSys.ws_TextFontGC = XCreateGC(x11_display, vw->vw_Window,
- GCForeground | GCBackground
- | GCLineWidth | GCFont,
- &xgcv);
- xgcv.foreground = x11_back_pixel;
- xgcv.background = x11_fore_pixel;
- vw->vw_WindowSys.ws_BlkFontGC = XCreateGC(x11_display, vw->vw_Window,
- GCForeground | GCBackground
- | GCLineWidth | GCFont,
- &xgcv);
- size_hints.x = x,
- size_hints.y = y,
- size_hints.width = width,
- size_hints.height = height,
- size_hints.base_width = 0;
- size_hints.base_height = vw->vw_FontY + 3;
- size_hints.width_inc = vw->vw_FontX;
- size_hints.height_inc = vw->vw_FontY;
- size_hints.min_width = size_hints.base_width + size_hints.width_inc;
- size_hints.min_height = size_hints.base_height + size_hints.height_inc;
- size_hints.flags |= PMinSize | PResizeInc | PBaseSize;
- wm_hints.flags = InputHint | StateHint;
- wm_hints.input = True;
- wm_hints.initial_state = NormalState;
- XSetWMProperties(x11_display, win, NULL, NULL, x11_argv, x11_argc, &size_hints, &wm_hints, &class_hints);
- XStoreName(x11_display, win, /* "jade" */ VERSSTRING);
- XSetWMProtocols(x11_display, win, &x11_wm_del_win, 1);
- XSelectInput(x11_display, win, INPUT_EVENTS);
- XMapWindow(x11_display, win);
- XDefineCursor(x11_display, win, x11_text_cursor);
- return(win);
- }
- return(FALSE);
- }
-
- void
- sys_kill_window(VW *vw)
- {
- XFreeGC(x11_display, vw->vw_WindowSys.ws_BlkFontGC);
- XFreeGC(x11_display, vw->vw_WindowSys.ws_TextFontGC);
- XDestroyWindow(x11_display, vw->vw_Window);
- }
-
- void
- sys_activate_win(VW *vw)
- {
- /* Not sure about all this?? */
- XRaiseWindow(x11_display, vw->vw_Window);
- XWarpPointer(x11_display, None, vw->vw_Window, 0, 0, 0, 0, 1, 1);
- }
-
- void
- sys_set_vw_pos(VW *vw, long x, long y, long w, long h)
- {
- XMoveResizeWindow(x11_display, vw->vw_Window,
- (unsigned int)x, (unsigned int)y,
- (unsigned int)w, (unsigned int)h);
- }
-
- VW *
- x11_find_window_view(Window win)
- {
- VW *vw = view_chain;
- while(vw)
- {
- if(vw->vw_Window == win)
- break;
- vw = vw->vw_Next;
- }
- return(vw);
- }
-
- int
- sys_set_font(VW *vw)
- {
- XFontStruct *font;
- if((font = XLoadQueryFont(x11_display, VSTR(vw->vw_FontName)))
- || (font = XLoadQueryFont(x11_display, DEFAULT_FONT)))
- {
- if(vw->vw_Font)
- XFreeFont(x11_display, vw->vw_Font);
- vw->vw_Font = font;
- vw->vw_FontX = XTextWidth(font, "M", 1);
- vw->vw_FontY = vw->vw_Font->ascent + vw->vw_Font->descent;
- if(vw->vw_Window)
- {
- int w, h;
- w = vw->vw_MaxX * vw->vw_FontX;
- h = ((vw->vw_MaxY + 1) * vw->vw_FontY) + 3;
- XSetFont(x11_display, vw->vw_WindowSys.ws_TextFontGC, font->fid);
- XSetFont(x11_display, vw->vw_WindowSys.ws_BlkFontGC, font->fid);
- sys_update_dimensions(vw);
- size_hints.width = w;
- size_hints.height = h;
- size_hints.base_width = 0;
- size_hints.base_height = vw->vw_FontY + 3;
- size_hints.width_inc = vw->vw_FontX;
- size_hints.height_inc = vw->vw_FontY;
- size_hints.min_width = size_hints.base_width + size_hints.width_inc;
- size_hints.min_height = size_hints.base_height + size_hints.height_inc;
- size_hints.flags = PResizeInc | PMinSize | PBaseSize;
- XSetWMNormalHints(x11_display, vw->vw_Window, &size_hints);
- XResizeWindow(x11_display, vw->vw_Window, w, h);
- #if 0
- vw->vw_DeferRefresh++;
- #endif
- }
- return(TRUE);
- }
- return(FALSE);
- }
-
- void
- sys_unset_font(VW *vw)
- {
- if(vw->vw_Font)
- {
- XFreeFont(x11_display, vw->vw_Font);
- vw->vw_Font = NULL;
- }
- }
-
- _PR VALUE cmd_set_font(VALUE fontname, VALUE vw);
- DEFUN_INT("set-font", cmd_set_font, subr_set_font, (VALUE fontname, VALUE vw), V_Subr2, DOC_set_font, "sFont name: ") /*
- ::doc:set_font::
- set-font FONT-NAME [WINDOW]
-
- FONT-NAME specifies the font to use in WINDOW (or the active one).
- Under X11 FONT-NAME is a standard font description, under AmigaDOS it is the
- name of the font followed by a dash and then the point size to use (for
- example "topaz.font-8" to get an 8-point topaz font).
- ::end:: */
- {
- VALUE oldfont;
- DECLARE1(fontname, STRINGP);
- if(!WINDOWP(vw))
- vw = VAL(curr_vw);
- oldfont = VWIN(vw)->vw_FontName;
- VWIN(vw)->vw_FontName = fontname;
- if(sys_set_font(VWIN(vw)))
- {
- VWIN(vw)->vw_Flags |= VWFF_FORCE_REFRESH;
- #if 0
- VWIN(vw)->vw_DeferRefresh++;
- #endif
- return(sym_t);
- }
- else
- {
- cmd_signal(sym_error, list_2(MKSTR("Can't open font"), fontname));
- VWIN(vw)->vw_FontName = oldfont;
- return(NULL);
- }
- }
-
- void
- sys_reset_sleep_titles(TX *tx)
- {
- }
-
- _PR VALUE cmd_screen_width(void);
- DEFUN("screen-width", cmd_screen_width, subr_screen_width, (void), V_Subr0, DOC_screen_width) /*
- ::doc:screen_width::
- screen-width
-
- Returns the width of the root window or screen in pixels.
- ::end:: */
- {
- Window root;
- int dummy1;
- unsigned int dummy2;
- int val;
- if(XGetGeometry(x11_display, DefaultRootWindow(x11_display),
- &root, &dummy1, &dummy1,
- (unsigned int *)&val, &dummy2,
- &dummy2, &dummy2))
- return(make_number(val));
- return(NULL);
- }
-
- _PR VALUE cmd_screen_height(void);
- DEFUN("screen-height", cmd_screen_height, subr_screen_height, (void), V_Subr0, DOC_screen_height) /*
- ::doc:screen_height::
- screen-height
-
- Returns the height of the root window or screen in pixels.
- ::end:: */
- {
- Window root;
- int dummy1;
- unsigned int dummy2;
- int val;
- if(XGetGeometry(x11_display, DefaultRootWindow(x11_display),
- &root, &dummy1, &dummy1,
- &dummy2, (unsigned int *)&val,
- &dummy2, &dummy2))
- return(make_number(val));
- return(NULL);
- }
-
- _PR VALUE cmd_window_left_edge(void);
- DEFUN("window-left-edge", cmd_window_left_edge, subr_window_left_edge, (void), V_Subr0, DOC_window_left_edge) /*
- ::doc:window_left_edge::
- window-left-edge
-
- Returns the x position of the current window relative to the origin of the
- root window or screen.
- ::end:: */
- {
- Window tmp;
- int x, y;
- if(XTranslateCoordinates(x11_display, curr_vw->vw_Window,
- DefaultRootWindow(x11_display), 0, 0, &x, &y, &tmp))
- return(make_number(x));
- return(NULL);
- }
-
- _PR VALUE cmd_window_top_edge(void);
- DEFUN("window-top-edge", cmd_window_top_edge, subr_window_top_edge, (void), V_Subr0, DOC_window_top_edge) /*
- ::doc:window_top_edge::
- window-top-edge
-
- Returns the y position of the current window relative to the origin of the
- root window or screen.
- ::end:: */
- {
- Window tmp;
- int x, y;
- if(XTranslateCoordinates(x11_display, curr_vw->vw_Window,
- DefaultRootWindow(x11_display), 0, 0, &x, &y, &tmp))
- return(make_number(y));
- return(NULL);
- }
-
- _PR VALUE cmd_window_width(void);
- DEFUN("window-width", cmd_window_width, subr_window_width, (void), V_Subr0, DOC_window_width) /*
- ::doc:window_width::
- window-width
-
- Returns the width, in pixels, of the current window.
- ::end:: */
- {
- Window root;
- int dummy1;
- unsigned int dummy2;
- int val;
- if(XGetGeometry(x11_display, curr_vw->vw_Window,
- &root, &dummy1, &dummy1,
- (unsigned int *)&val, &dummy2,
- &dummy2, &dummy2))
- return(make_number(val));
- return(NULL);
- }
-
- _PR VALUE cmd_window_height(void);
- DEFUN("window-height", cmd_window_height, subr_window_height, (void), V_Subr0, DOC_window_height) /*
- ::doc:window_height::
- window-height
-
- Returns the height, in pixels, of the current window.
- ::end:: */
- {
- Window root;
- int dummy1;
- unsigned int dummy2;
- int val;
- if(XGetGeometry(x11_display, curr_vw->vw_Window,
- &root, &dummy1, &dummy1,
- &dummy2, (unsigned int *)&val,
- &dummy2, &dummy2))
- return(make_number(val));
- return(NULL);
- }
-
- _PR VALUE cmd_window_bar_height(void);
- DEFUN("window-bar-height", cmd_window_bar_height, subr_window_bar_height, (void), V_Subr0, DOC_window_bar_height) /*
- ::doc:window_bar_height::
- window-bar-height
-
- On an Amiga returns the number of pixels high the title bar of the window
- is. This is 0 in X11.
- ::end:: */
- {
- return(make_number(0));
- }
-
- bool
- sys_get_mouse_pos(POS *pos, VW *vw)
- {
- Window tmpw;
- int tmp;
- int x, y;
- if(XQueryPointer(x11_display, vw->vw_Window, &tmpw, &tmpw, &tmp, &tmp, &x, &y, &tmp))
- {
- x = (x - vw->vw_XStartPix) / vw->vw_FontX;
- y = (y - vw->vw_YStartPix) / vw->vw_FontY;
- if((x < 0) || (y < 0) || (x >= vw->vw_MaxX) || (y >= vw->vw_MaxY))
- return(FALSE);
- pos->pos_Col = x + vw->vw_StartCol;
- pos->pos_Line = y + vw->vw_StartLine;
- if(pos->pos_Col < 0)
- pos->pos_Col = 0;
- if(pos->pos_Line < 0)
- pos->pos_Line = 0;
- if(pos->pos_Line >= vw->vw_Tx->tx_NumLines)
- pos->pos_Line = vw->vw_Tx->tx_NumLines - 1;
- pos->pos_Col = char_col(vw->vw_Tx, x + vw->vw_StartCol, pos->pos_Line);
- return(TRUE);
- }
- return(FALSE);
- }
-
- _PR VALUE cmd_flush_output(void);
- DEFUN("flush-output", cmd_flush_output, subr_flush_output, (void), V_Subr0, DOC_flush_output) /*
- ::doc:flush_output::
- flush-output
-
- Forces any cached window output to be drawn. This is usually unnecessary.
- ::end:: */
- {
- XFlush(x11_display);
- return(sym_t);
- }
-
- void
- sys_windows_init(void)
- {
- ADD_SUBR(subr_set_font);
- ADD_SUBR(subr_screen_width);
- ADD_SUBR(subr_screen_height);
- ADD_SUBR(subr_window_left_edge);
- ADD_SUBR(subr_window_top_edge);
- ADD_SUBR(subr_window_width);
- ADD_SUBR(subr_window_height);
- ADD_SUBR(subr_window_bar_height);
- ADD_SUBR(subr_flush_output);
- }
-